package com.tender.impl;

import com.google.common.base.Objects;
import com.tender.RouterDiscoveryBizService;
import com.tender.constants.Constants;
import com.tender.constants.WebSocketConstants;
import com.tender.converter.RouterDiscoveryConverter;
import com.tender.dto.HostInfoDTO;
import com.tender.enums.ServiceTypeEnums;
import com.tender.utils.RedisUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

@Service
public class RouterDiscoveryBizServiceImpl implements RouterDiscoveryBizService {

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private RedisUtils redisUtils;

    @Override
    public HostInfoDTO getHostInfo(String serviceType, String applicationName) {
        if (StringUtils.isBlank(serviceType)) {
            serviceType = ServiceTypeEnums.COMMON.name();
        }

        ServiceTypeEnums serviceTypeEnum = ServiceTypeEnums.getServiceType(serviceType);
        if (null == serviceTypeEnum) {
            // TODO
            throw new RuntimeException("服务类型错误");
        }

        // 最终结果
        HostInfoDTO hostInfoDTO = null;

        if (Objects.equal(serviceTypeEnum, ServiceTypeEnums.COMMON)) {
            if (StringUtils.isBlank(applicationName)) {
                // TODO
                throw new RuntimeException("应用名称不能为空");
            }
            List<ServiceInstance> instances = discoveryClient.getInstances(applicationName);
            if (!CollectionUtils.isEmpty(instances)) {
                Random random = new Random();
                int n = random.nextInt(instances.size());
                ServiceInstance serviceInstance = instances.get(n);
                hostInfoDTO = RouterDiscoveryConverter.converter2HostInfoDTO(applicationName, serviceInstance);
            }
        } else {
            // 针对 web socket 集群，每个服务名称都是独一无二的
            List<String> instanceNameList = discoveryClient.getServices();
            instanceNameList = instanceNameList.stream().filter(instanceName ->
                    instanceName.startsWith(Constants.APPLICATION_NAME_PREFIX)).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(instanceNameList)) {
                Random random = new Random();
                int index = random.nextInt(instanceNameList.size());
                List<ServiceInstance> instances = discoveryClient.getInstances(instanceNameList.get(index));
                if (!CollectionUtils.isEmpty(instances)) {
                    // 每个服务名，只对应一个实例
                    hostInfoDTO = RouterDiscoveryConverter.converter2HostInfoDTO(applicationName, instances.get(0));
                }
            }
        }

        return hostInfoDTO;
    }

    @Override
    public List<HostInfoDTO> getHostInfoList(String serviceType, String applicationName) {
        if (StringUtils.isBlank(serviceType)) {
            serviceType = ServiceTypeEnums.COMMON.name();
        }

        ServiceTypeEnums serviceTypeEnum = ServiceTypeEnums.getServiceType(serviceType);
        if (null == serviceTypeEnum) {
            // TODO
            throw new RuntimeException("服务类型错误");
        }

        if (Objects.equal(serviceTypeEnum, ServiceTypeEnums.COMMON)) {
            if (StringUtils.isBlank(applicationName)) {
                // TODO
                throw new RuntimeException("应用名称不能为空");
            }
            List<ServiceInstance> instances = discoveryClient.getInstances(applicationName);
            if (!CollectionUtils.isEmpty(instances)) {
                return RouterDiscoveryConverter.converter2HostInfoDTOList(applicationName, instances);
            }
        } else {
            List<String> instanceNameList = discoveryClient.getServices();
            instanceNameList = instanceNameList.stream().filter(item ->
                    item.startsWith(Constants.APPLICATION_NAME_PREFIX)).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(instanceNameList)) {
                // 结果收集器
                List<HostInfoDTO> list = new ArrayList<>();
                instanceNameList.forEach(instanceName -> {
                    List<ServiceInstance> instances = discoveryClient.getInstances(instanceName);
                    if (!CollectionUtils.isEmpty(instances)) {
                        // 每个服务名，只对应一个实例
                        list.add(RouterDiscoveryConverter.converter2HostInfoDTO(instanceName, instances.get(0)));
                    }
                });
                return list;
            }
        }

        return new ArrayList<>();
    }

    @Override
    public HostInfoDTO randomWsInfoByUserId(String userId) {
        String applicationName = (String) redisUtils.get(userId);
        if (StringUtils.isNotBlank(applicationName)) {
            return this.getHostInfo(ServiceTypeEnums.COMMON.name(), applicationName);
        } else {
            return this.getHostInfo(ServiceTypeEnums.WS.name(), null);
        }
    }
}